package net.freestu.sola.web.spider.ballerina.core;


import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.freestu.sola.web.global.AllLinksHashtable;
import net.freestu.sola.web.global.AllPagesCounter;
import net.freestu.sola.web.global.AllUrlQueues;
import net.freestu.sola.web.global.GlobleVar;
import net.freestu.sola.web.global.LinkHash;
import net.freestu.sola.web.global.PageCounter;
import net.freestu.sola.web.global.ThreadPool;
import net.freestu.sola.web.spider.ballerina.myUtil.UrlQueue;
import net.freestu.sola.web.util.FileManager;
import net.freestu.sola.web.util.MyLogger;


public class Spider extends Thread {

	private String name;//这里的名字应该有www.
    private String url;
    int level;
    
	public Spider(String str) {

		super(str);
		
		//这里的str是202.110.111.111。 baidu.com  。 sina.com 。 202.110.111.111$8080
		level=1;//这个地方需要进行修改，如果是种子站点(cdut.edu.cn),则为1。其他则为2.
		name = str;
		String ss=str.replace("$", ":");
		Pattern p = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?");
	    Matcher m = p.matcher(ss);
	    if(m.find()){
	    	url="http://"+ss;
	    }else{
		    url=GlobleVar.WEB_NAME+name;
	    }
	}

	/**
	 * 返回层次数。这个地方通过线程来共享数据也是很方便的啊。
	 * @return
	 */
	public int getLevel(){
		
		return level;
	}
	
	
	public void run() {

		register();
		// 对爬行的行站点进行注册。
		// 3.开始爬行。
		// 4.下载种子站点
		
		PageFetcher pf1 = new PageFetcher(url, GlobleVar.EXEFOLDER+
				File.separator+"Crawl Folder"+
				File.separator + name+ File.separator+
				"PageDB", name,level);
		//level传递的是真实的层数。cdut.edu.cn 是第一层.
			
		pf1.download();
		
		//-------检测是否测试成功---------------------------------------------------
		File fn=new File(GlobleVar.EXEFOLDER+File.separator+
				"Crawl Folder"+File.separator+name+
				File.separator+"PageDB"+File.separator+"P1");
		
		//再次判断，如果没有则将对象进行destory.
		if(!fn.exists()){
		  
		    ThreadPool tp=ThreadPool.getInstance();
		    try {
			  tp.destory(name);
		    }catch (RuntimeException e) {
			//e.printStackTrace();
		    }
		   return;
		}
		//----------------------------------------------------------------------
		AllLinksHashtable alltable = AllLinksHashtable.getInstance();
		LinkHash table=alltable.get(name);
		table.put(url);//将种子放进Hash表中.避免再重复爬行.
		//----------------------------------------------------------------------
		ThreadPool tp=ThreadPool.getInstance();
		tp.createOneSpider();//这里表示生成了一个蜘蛛，计数+1。
		
		//--------
		int Flag1=1;//第一层的网页数为1.
		// ------------------------------------------------------------------------------

		// 5.提取链接，放入下载列队中，和全局Hash表中。
		UrlPicker up = new UrlPicker(GlobleVar.EXEFOLDER+
				File.separator+"Crawl Folder"+
				File.separator+name+File.separator+
				"PageDB"+File.separator+"P1",
				name);
		
		up.readLinks();// 2)读链接
		up.complexFilter();// 1)过滤,这个里面的过滤顺序必须要考虑好。
		up.addLinksToHash();// #3)加入全局的Hash，这个地方入队列。
		up.saveToLinkDB(GlobleVar.EXEFOLDER+File.separator+"Crawl Folder"+
				File.separator+ name + File.separator+"LinkDB", "L");// 4)存入L表中。
		//-----------------------------------------------------------------------------------

		// 第二部分开始

		// 5.从URL列队之中提取链接顺序下载。
		int levell=GlobleVar.CRAWL_LEVEL;
		level++;
		int l=1;
		int Flag2;

		while (true) {//一层一个循环。
			
			AllUrlQueues auq = AllUrlQueues.getInstance();
			UrlQueue uq = auq.get(name);
			// ----------下载网页---------------------
			FileManager.buildDir(GlobleVar.EXEFOLDER+
					File.separator+"Crawl Folder"+
					File.separator+ name + 
					File.separator+"PageDB",
					"PageDB"+ l);
			
			while (uq.members() > 0) {// 下载网页。将队列中的链接全部下载完。
				
				String theurl = uq.pop();// 1.提出链接。
				int i = uq.members();// ?这里必须把int转化为string 吗？
				String sss = Integer.toString(i);
                //System.out.println("该层倒计时"+sss);

				if (theurl != null) {

					//下载theurl页面.
					PageFetcher thepf = new PageFetcher(
							theurl,
							GlobleVar.EXEFOLDER+File.separator+
							"Crawl Folder"+File.separator + name +
							File.separator+
							"PageDB"+File.separator + "PageDB" + l,
							name,level);//
					
					thepf.download();// 下载
				} else{
					break;
				}
		}		
			//-----------------------------------
			l++;//具体的层次。l为2层次
			level++;//虚拟的层次
            if(l>levell) break;
            //------------------------------------
            
			AllPagesCounter apc=AllPagesCounter.getInstance();
			PageCounter pc=apc.get(name);
			Flag2=pc.getPageNum();//得到Flag2(网页数量）	
			
			int le=l-1;//le为2
			
			for (int filenum=Flag1+1;filenum <=Flag2-Flag1; filenum++){

				UrlPicker moreup = new UrlPicker(GlobleVar.EXEFOLDER+File.separator+
						"Crawl Folder"+File.separator+name+File.separator+
						"PageDB"+File.separator+"PageDB" + (le) + File.separator
						+ "P"+filenum,name);
				
				MyLogger.log("正在提取第层"+le+"链接状态中~~~");
				
				
				try {
					moreup.readLinks();// 2)读链接
				}catch (Exception e) {
					
					System.out.println(Thread.currentThread().getName()+":::"+GlobleVar.EXEFOLDER+File.separator+
							"Crawl Folder"+File.separator+name+File.separator+
							"PageDB"+File.separator+"PageDB" + (le) + File.separator
							+ "P"+filenum);
					e.printStackTrace();
				}
				moreup.complexFilter();// 1)过滤
				moreup.addLinksToHash();// #3)加入全局的Hash，这个地方入队列。
				moreup.saveToLinkDB(GlobleVar.EXEFOLDER+File.separator+"Crawl Folder"+
						File.separator+name+File.separator+"LinkDB", "L" +(le));// 4)存入L1表中。

			}
			Flag1=Flag2;
		}
		
		
		//--------
		AllPagesCounter apc=AllPagesCounter.getInstance();
		PageCounter pc=apc.get(name);
		//---------
		
		
		//##这里是爬行结束后Spider的信息。以后可供扩展。?出现了一个问题，数目少了一个。
		MyLogger.log("死亡--->抓取的网页数："+pc.getPageNum());
		//抓取结束后应该让活动的Spider数量减少
		ThreadPool tp1=ThreadPool.getInstance();
		tp1.dieOneSpider();//这里表示让一只蜘蛛死亡，计数-1
	 }
	

	public void register() {

		// 1.创建www.cdut.edu.cn文件夹
		setFolder(name);
		
		// 2.得到在本线程的全局变量
		AllLinksHashtable aht = AllLinksHashtable.getInstance();
		aht.put(name);// 在全局Hashtable中注册。
		aht.putun(name);//不能连接的链接
		AllPagesCounter apc = AllPagesCounter.getInstance();
		apc.put(name);// 在全局网页计数器中注册。
		AllUrlQueues auq = AllUrlQueues.getInstance();
		auq.put(name);// 注册URL爬行队列。
		MyLogger.log("register the seed:" + name);
	}

	/**
	 * create all folders which is usefull using the name
	 * @param name
	 */
	private void setFolder(String name) {

		FileManager.buildDir(GlobleVar.EXEFOLDER+File.separator+"Crawl Folder", name);
		FileManager.buildDir(GlobleVar.EXEFOLDER+File.separator+"Crawl Folder" +File.separator+ name, "PageDB");
		FileManager.buildDir(GlobleVar.EXEFOLDER+File.separator+"Crawl Folder"+File.separator+ name, "LinkDB");
		FileManager.buildFile(GlobleVar.EXEFOLDER+File.separator+"Crawl Folder"+File.separator + name, "LinkHash");
	}
}